home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / pcl_src.zoo / boot.lsp < prev    next >
Lisp/Scheme  |  1992-08-29  |  106KB  |  2,248 lines

  1. ;;;-*-Mode: LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
  2. ;;;
  3. ;;; *************************************************************************
  4. ;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
  5. ;;; All rights reserved.
  6. ;;;
  7. ;;; Use and copying of this software and preparation of derivative works
  8. ;;; based upon this software are permitted.  Any distribution of this
  9. ;;; software or derivative works must comply with all applicable United
  10. ;;; States export control laws.
  11. ;;; 
  12. ;;; This software is made available AS IS, and Xerox Corporation makes no
  13. ;;; warranty about the software, its performance or its conformity to any
  14. ;;; specification.
  15. ;;; 
  16. ;;; Any person obtaining a copy of this software is requested to send their
  17. ;;; name and post office or electronic mail address to:
  18. ;;;   CommonLoops Coordinator
  19. ;;;   Xerox PARC
  20. ;;;   3333 Coyote Hill Rd.
  21. ;;;   Palo Alto, CA 94304
  22. ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  23. ;;;
  24. ;;; Suggestions, comments and requests for improvements are also welcome.
  25. ;;; *************************************************************************
  26. ;;;
  27.  
  28. (in-package 'pcl)
  29.  
  30. #|
  31.  
  32. The CommonLoops evaluator is meta-circular.  
  33.  
  34. Most of the code in PCL is methods on generic functions, including most of
  35. the code that actually implements generic functions and method lookup.
  36.  
  37. So, we have a classic bootstrapping problem.   The solution to this is to
  38. first get a cheap implementation of generic functions running, these are
  39. called early generic functions.  These early generic functions and the
  40. corresponding early methods and early method lookup are used to get enough
  41. of the system running that it is possible to create real generic functions
  42. and methods and implement real method lookup.  At that point (done in the
  43. file FIXUP) the function fix-early-generic-functions is called to convert
  44. all the early generic functions to real generic functions.
  45.  
  46. The cheap generic functions are built using the same funcallable-instance
  47. objects real generic-functions are made out of.  This means that as PCL
  48. is being bootstrapped, the cheap generic function objects which are being
  49. created are the same objects which will later be real generic functions.
  50. This is good because:
  51.   - we don't cons garbage structure
  52.   - we can keep pointers to the cheap generic function objects
  53.     during booting because those pointers will still point to
  54.     the right object after the generic functions are all fixed
  55.     up
  56.  
  57.  
  58.  
  59. This file defines the defmethod macro and the mechanism used to expand it.
  60. This includes the mechanism for processing the body of a method.  defmethod
  61. basically expands into a call to load-defmethod, which basically calls
  62. add-method to add the method to the generic-function.  These expansions can
  63. be loaded either during bootstrapping or when PCL is fully up and running.
  64.  
  65. An important effect of this structure is it means we can compile files with
  66. defmethod forms in them in a completely running PCL, but then load those files
  67. back in during bootstrapping.  This makes development easier.  It also means
  68. there is only one set of code for processing defmethod.  Bootstrapping works
  69. by being sure to have load-method be careful to call only primitives which
  70. work during bootstrapping.
  71.  
  72. |#
  73.  
  74. (proclaim '(notinline make-a-method
  75.                       add-named-method                
  76.                       call-make-method-lambda
  77.                       call-make-closure-generator-form
  78.                       call-store-method-function-p
  79.                       call-store-method-optimized-function-p
  80.                       call-store-closure-generator-p
  81.                       call-store-optimized-method-lambda-p
  82.  
  83.                       ensure-generic-function-using-class
  84.  
  85.                       add-method
  86.                       remove-method
  87.                       ))
  88.  
  89. (defvar *early-functions*
  90.         '((make-a-method early-make-a-method
  91.                          real-make-a-method)
  92.           (add-named-method early-add-named-method
  93.                             real-add-named-method)
  94.           (call-make-method-lambda early-make-method-lambda
  95.                                    make-method-lambda)
  96.           (call-make-closure-generator-form make-std-closure-generator-form
  97.                                             make-closure-generator-form)
  98.           (call-store-method-function-p early-store-method-function-p
  99.                                         store-method-function-p)
  100.           (call-store-method-optimized-function-p
  101.              early-store-method-optimized-function-p
  102.              store-method-optimized-function-p)
  103.           (call-store-closure-generator-p early-store-closure-generator-p
  104.                                           store-closure-generator-p)
  105.           (call-store-optimized-method-lambda-p
  106.              early-store-optimized-method-lambda-p
  107.              store-optimized-method-lambda-p)
  108.           ))
  109.  
  110. ;;;
  111. ;;; For each of the early functions, arrange to have it point to its early
  112. ;;; definition.  Do this in a way that makes sure that if we redefine one
  113. ;;; of the early definitions the redefinition will take effect.  This makes
  114. ;;; development easier.
  115. ;;;
  116. ;;; The function which generates the redirection closure is pulled out into
  117. ;;; a separate piece of code because of a bug in ExCL which causes this not
  118. ;;; to work if it is inlined.
  119. ;;;
  120. (eval-when (load eval)
  121.  
  122.   (defun redirect-early-function-internal (to)
  123.     #'(lambda (&rest args) (apply-function (symbol-function to) args)))
  124.   
  125.   (dolist (fns *early-functions*)
  126.     (let ((name (car fns))
  127.           (early-name (cadr fns)))
  128.       (setf (symbol-function name)
  129.             (redirect-early-function-internal early-name))))
  130.  
  131.   )
  132.  
  133.  
  134. ;;;
  135. ;;; *generic-function-fixups* is used by fix-early-generic-functions to
  136. ;;; convert the few functions in the bootstrap which are supposed to be
  137. ;;; generic functions but can't be early on.
  138. ;;; 
  139. (defvar *generic-function-fixups*
  140.     '((add-method
  141.         ((generic-function method)                      ;lambda-list
  142.          (standard-generic-function method)             ;specializers
  143.          real-add-method))                              ;method-function
  144.       (remove-method
  145.         ((generic-function method)
  146.          (standard-generic-function method)
  147.          real-remove-method))
  148.       (get-method
  149.         ((generic-function qualifiers specializers &optional (errorp t))
  150.          (standard-generic-function t t)
  151.          real-get-method))
  152.       (ensure-generic-function-using-class
  153.         ((generic-function function-specifier
  154.                            &key generic-function-class environment
  155.                            &allow-other-keys)
  156.          (generic-function t)
  157.          real-ensure-gf-using-class--generic-function)
  158.         ((generic-function function-specifier
  159.                            &key generic-function-class environment
  160.                            &allow-other-keys)
  161.          (null t)
  162.          real-ensure-gf-using-class--null))
  163.       ))
  164.  
  165.  
  166. ;;;
  167. ;;;
  168. ;;;
  169. (defmacro defgeneric (function-specifier lambda-list &body options)
  170.   (expand-defgeneric function-specifier lambda-list options))
  171.  
  172. (defvar *defgeneric-temp* NIL)
  173.  
  174. (defun expand-defgeneric (function-specifier lambda-list options)
  175.   (when (listp function-specifier) (do-standard-defsetf-1 (cadr function-specifier)))
  176.   (let ((initargs ())
  177.         (methods  ()))
  178.     (flet ((duplicate-option (name)
  179.              (error "The option ~S appears more than once." name)))
  180.       ;;
  181.       ;; INITARG takes this screwy new argument to get around a bad
  182.       ;; interaction between lexical macros and setf in the Lucid
  183.       ;; compiler.
  184.       ;; 
  185.       (macrolet ((initarg (key &optional new)
  186.                    (if new
  187.                        `(setf (getf initargs ,key) ,new)
  188.                        `(getf initargs ,key))))
  189.         (dolist (option options)
  190.           (ecase (car option)
  191.             (:argument-precedence-order
  192.               (if (initarg :argument-precedence-order)
  193.                   (duplicate-option :argument-precedence-order)
  194.                   (initarg :argument-precedence-order `',(cdr option))))
  195.             (declare
  196.               (initarg :declarations
  197.                        (append (cdr option) (initarg :declarations))))
  198.             (:documentation
  199.               (if (initarg :documentation)
  200.                   (duplicate-option :documentation)
  201.                   (initarg :documentation `',(cadr option))))
  202.             (:method-combination
  203.               (if (initarg :method-combination)
  204.                   (duplicate-option :method-combination)
  205.                   (initarg :method-combination `',(cdr option))))
  206.             (:generic-function-class
  207.               (if (initarg :generic-function-class)
  208.                   (duplicate-option :generic-function-class)
  209.                   (initarg :generic-function-class `',(cadr option))))
  210.             (:method-class
  211.               (if (initarg :method-class)
  212.                   (duplicate-option :method-class)
  213.                   (initarg :method-class `',(cadr option))))
  214.             (:method
  215.               (push (cdr option) methods))))
  216.  
  217.         (let ((declarations (initarg :declarations)))
  218.           (when declarations (initarg :declarations `',declarations)))))
  219.      (let ((load-defgeneric-form
  220.              (make-top-level-form `(defgeneric ,function-specifier)
  221.                *defgeneric-times*
  222.                `(load-defgeneric ',function-specifier ',lambda-list ,@initargs))))
  223.        (if methods
  224.            `(progn
  225.               (proclaim-defgeneric ',function-specifier ',lambda-list)
  226.               (setf *defgeneric-temp* ,load-defgeneric-form)
  227.               ,@(mapcar #'(lambda (method-descrip)
  228.                            `(defmethod ,function-specifier ,@method-descrip))
  229.                         (nreverse methods))
  230.               (prog1 *defgeneric-temp* (setf *defgeneric-temp* NIL)))
  231.            `(progn
  232.               (proclaim-defgeneric ',function-specifier ',lambda-list)
  233.               ,load-defgeneric-form)))))
  234.  
  235.  
  236. (defun load-defgeneric (function-specifier lambda-list &rest initargs)
  237.   (when (listp function-specifier) (do-standard-defsetf-1 (cadr function-specifier)))
  238.   (apply #'ensure-generic-function
  239.          function-specifier
  240.          :lambda-list lambda-list
  241.          :definition-source `((defgeneric ,function-specifier)
  242.                               ,(load-truename))
  243.          initargs))
  244.  
  245.  
  246. ;;;
  247. ;;;
  248. ;;;
  249.  
  250. (declaim (ftype (function (T) (values T T T T)) parse-defmethod))
  251.  
  252. (defmacro DEFMETHOD (&rest args &environment env)
  253.   #+(or (not :lucid) :lcl3.0)   
  254.   (declare (arglist name
  255.                     {method-qualifier}*
  256.                     specialized-lambda-list
  257.                     &body body))
  258.   (multiple-value-bind (name qualifiers lambda-list body)
  259.       (parse-defmethod args)
  260.     (let ((proto-gf
  261.             (prototype-of-generic-function name))
  262.           (proto-method
  263.             (method-prototype-for-gf name)))
  264.       (expand-defmethod
  265.         proto-gf proto-method name qualifiers lambda-list body env))))
  266.  
  267. ;;;
  268. ;;; takes a name which is either a generic function name or a list specifying
  269. ;;; a setf generic function (like: (SETF <generic-function-name>)).  Returns
  270. ;;; the prototype instance of the method-class for that generic function.
  271. ;;;
  272. ;;; If there is no generic function by that name, this returns the default
  273. ;;; value, the prototype instance of the class STANDARD-METHOD.  This default
  274. ;;; value is also returned if the spec names an ordinary function or even a
  275. ;;; macro.  In effect, this leaves the signalling of the appropriate error
  276. ;;; until load time.
  277. ;;;
  278. ;;; NOTE that during bootstrapping, this function is allowed to return NIL.
  279. ;;; 
  280. (defun method-prototype-for-gf (name)      
  281.   (let ((gf? (and (gboundp name)
  282.                   (gdefinition name))))
  283.     (cond ((neq *boot-state* 'complete) nil)
  284.           ((or (null gf?)
  285.                (not (generic-function-p gf?)))          ;Someone else MIGHT
  286.                                                         ;error at load time.
  287.            (class-prototype (find-class 'standard-method)))
  288.           (t
  289.             (let ((method-class (or (generic-function-method-class gf?)
  290.                                     (find-class 'standard-method))))
  291.               (unless (class-finalized-p method-class)
  292.                 (finalize-inheritance method-class))
  293.               (class-prototype method-class))))))
  294.  
  295. (defun prototype-of-generic-function (name)
  296.   ;;   Takes a name which is either a generic function name or a list specifying
  297.   ;; a setf generic function (like: (SETF <generic-function-name>)).
  298.   ;;   Returns the generic function itself, unless the generic-function has
  299.   ;; not yet been defined, in which case it returns the class-prototype
  300.   ;; of 'standard-generic-function.
  301.   ;;
  302.   ;; NOTE that during bootstrapping, this function is allowed to return NIL.
  303.   ;; 
  304.   (let ((gf? (and (gboundp name)
  305.                   (gdefinition name))))
  306.     (cond ((neq *boot-state* 'complete) nil)
  307.           ((or (null gf?) (not (generic-function-p gf?)))
  308.            (let ((std-generic-function-class
  309.                    (find-class 'standard-generic-function NIL)))
  310.               (if std-generic-function-class
  311.                   (class-prototype std-generic-function-class))))
  312.           (T gf?))))
  313.  
  314.  
  315. (defconstant *standard-pcl-make-method-lambda-doc-string*
  316.    "Standard PCL make-method-lambda here.")
  317.  
  318. (defun early-store-method-function-p
  319.        (generic-function method initargs)
  320.   ;; Should methods of this generic-function store their own method-function?
  321.   ;; Answer is normally T to keep stay compatible with the AMOP even
  322.   ;; though PCL actually uses the function in method-optimized-function
  323.   ;; for efficiency.  However, answer can be NIL if the programmer doesn't
  324.   ;; care about method-functions, which will cut down on binary sizes
  325.   ;; significantly since it would stop methods from carrying around
  326.   ;; an extra (unused) method-function.
  327.   ;; 
  328.   (declare (ignore generic-function method initargs))
  329.   *standard-store-method-function-p*)
  330.  
  331. (defun early-store-method-optimized-function-p
  332.        (generic-function method initargs)
  333.   ;; Should methods of this generic-function store their own
  334.   ;; method-optimized-function?
  335.   ;;   Answer better be T unless a closure-generator is stored
  336.   ;; for the method instead, or if the programmer has redefined the
  337.   ;; discriminating method function dispatch code to use the
  338.   ;; documented method-functions rather than the optimized PCL
  339.   ;; method-optimized-functions,
  340.   (declare (ignore generic-function method))
  341.   (null (memq :optimized-slot-indices initargs)))
  342.  
  343. (defun early-store-closure-generator-p
  344.        (generic-function method initargs)
  345.   ;; Should methods of this generic-function store their own
  346.   ;; method function closure generators?
  347.   ;;   Answer better be T unless a method-optimized-function is
  348.   ;; stored instead, or if the programmer has redefined the
  349.   ;; the discriminating method function dispatch code to use
  350.   ;; the documented method-functions rather than the optimized
  351.   ;; PCL method-optimized-functions.
  352.   (declare (ignore generic-function method))
  353.   (not (null (memq :optimized-slot-indices initargs))))
  354.  
  355. (defun early-store-optimized-method-lambda-p
  356.        (generic-function method initargs)
  357.   ;;   Should methods of this generic-function store their own
  358.   ;; their optimized-method-lambdas?
  359.   ;;   Generally only stored when the method contains slot-value
  360.   ;; accesses on its parameter lists, in which case the lambda
  361.   ;; is used to compile the cached method at runtime to directly
  362.   ;; optimize those accesses.
  363.   (declare (ignore generic-function method))
  364.   (and *compile-slot-access-method-functions-at-runtime-p*
  365.        (not (null (memq :optimized-slot-indices initargs)))))
  366.  
  367.  
  368. ;#-Genera
  369. (defun expand-defmethod
  370.        (proto-generic-function proto-method name qualifiers lambda-list
  371.         body env)
  372.   (when (listp name) (do-standard-defsetf-1 (cadr name)))
  373.   (multiple-value-bind (method-lambda optimized-method-lambda closure-generator
  374.                         initargs specializers doc)
  375.       (expand-defmethod-internal proto-generic-function proto-method
  376.                                  name qualifiers lambda-list body env)
  377.     (make-top-level-form `(defmethod ,name ,@qualifiers ,specializers)
  378.                          *defmethod-times*
  379.       `(progn
  380.          (proclaim-defgeneric ',name ',lambda-list)
  381.          (load-defmethod
  382.           ',(if proto-method
  383.                 (class-name (class-of proto-method))
  384.                 'standard-method)
  385.           ',name
  386.           ',qualifiers
  387.           (list ,@(mapcar #'(lambda (specializer)
  388.                               (if (consp specializer)
  389.                                   ``(,',(car specializer) ,,(cadr specializer))
  390.                                   `',specializer))
  391.                           specializers))
  392.           ',(extract-lambda-list lambda-list)
  393.           ',doc
  394.           ,(if method-lambda `(function ,method-lambda))
  395.           ,(if optimized-method-lambda `(function ,optimized-method-lambda))
  396.           ,closure-generator
  397.           ',initargs)))))
  398.  
  399. #||
  400. #+Genera
  401. (defun expand-defmethod (proto-method name qualifiers lambda-list body env)
  402.   (when (listp name) (do-standard-defsetf-1 (cadr name)))
  403.   (multiple-value-bind (fn-form specializers doc plist)
  404.       (expand-defmethod-internal name qualifiers lambda-list body env)
  405.     (let ((fn-args (cadadr fn-form))
  406.           (fn-body (cddadr fn-form))
  407.           (method-name `(method ,name ,@qualifiers ,specializers)))
  408.       `(progn
  409.          (proclaim '(function ,name))
  410.          (defun ,method-name ,fn-args
  411.            ,@fn-body)
  412.          (load-defmethod
  413.            ',(if proto-method
  414.                  (class-name (class-of proto-method))
  415.                  'standard-method)
  416.            ',name
  417.            ',qualifiers
  418.            (list ,@(mapcar #'(lambda (specializer)
  419.                                (if (consp specializer)
  420.                                    ``(,',(car specializer) ,,(cadr specializer))
  421.                                    `',specializer))
  422.                            specializers))
  423.            ',(extract-lambda-list lambda-list)
  424.            ',doc
  425.            ',(getf plist :isl-cache-symbol)     ;Paper over a bug in KCL by
  426.                                                 ;passing the cache-symbol
  427.                                                 ;here in addition to in the
  428.                                                 ;plist.
  429.            ',plist
  430.            #',method-name)))))
  431. ||#
  432.  
  433. (defvar *expand-defmethod-internal-real-body* NIL)
  434.  
  435. (defun expand-defmethod-internal
  436.        (proto-generic-function proto-method generic-function-name
  437.         qualifiers specialized-lambda-list body env)
  438.   (declare (ignore qualifiers))
  439.   (declare (values fn-form optimized-fn-form closure-generator-form
  440.                    initargs specializers doc))
  441.   (when (listp generic-function-name)
  442.     (do-standard-defsetf-1 (cadr generic-function-name)))
  443.   (multiple-value-bind (documentation declarations real-body)
  444.       (extract-declarations body)
  445.     (multiple-value-bind (parameters lambda-list specializers)
  446.         (parse-specialized-lambda-list specialized-lambda-list)
  447.       (let* ((required-parameters
  448.                (mapcar #'(lambda (r s) (declare (ignore s)) r)
  449.                        parameters
  450.                        specializers))
  451.              (parameters-to-reference
  452.                (make-parameter-references specialized-lambda-list
  453.                                           required-parameters
  454.                                           declarations
  455.                                           generic-function-name
  456.                                           specializers))
  457.              (class-declarations 
  458.                `(declare
  459.                   ,@(remove nil
  460.                             (mapcar #'(lambda (a s) (and (symbolp s)
  461.                                                          (neq s 't)
  462.                                                          `(class ,a ,s)))
  463.                                     parameters
  464.                                     specializers))))
  465.              (lambda-expression
  466.                ;; Remove the documentation string and insert the
  467.                ;; appropriate class declarations.  The documentation
  468.                ;; string is removed to make it easy for us to insert
  469.                ;; new declarations later, they will just go after the
  470.                ;; cadr of the method lambda.  The class declarations
  471.                ;; are inserted to communicate the class of the method's
  472.                ;; arguments to the code walk.
  473.                (let ()
  474.                  `(lambda ,lambda-list
  475.                     ,class-declarations
  476.                     ,@declarations
  477.                     (progn ,@parameters-to-reference)
  478.                     (block ,(if (listp generic-function-name)
  479.                                 (cadr generic-function-name)
  480.                                 generic-function-name)
  481.                       ,@real-body)))))
  482.         (let ((*expand-defmethod-internal-real-body* real-body))
  483.           (multiple-value-bind
  484.               (function optimized-function closure-generator initargs)
  485.             (make-method-lambda-and-optimized-lambda
  486.                 proto-generic-function proto-method lambda-expression env)
  487.             (values function
  488.                     optimized-function
  489.                     closure-generator
  490.                     initargs
  491.                     specializers
  492.                     documentation)))))))
  493.  
  494.  
  495. (declaim (ftype (function (T T T T) (values list list))
  496.         call-make-method-lambda
  497.         call-make-optimized-method-lambda))
  498.  
  499. (defvar *optimized-method-lambda* NIL)
  500.  
  501. (defun make-method-lambda-and-optimized-lambda
  502.   (generic-function method lambda-expression env)
  503.   ;;   Given the method body lambda-expression from expand-defmethod-internal,
  504.   ;; this method calls make-method-lambda to make the method-functions.
  505.   ;;   To adhere to the AMOP while retaining maximum efficiency, method
  506.   ;; functions are actually stored in two ways: as a (1) METHOD-FUNCTION and
  507.   ;; (2) as a METHOD-OPTIMIZED-FUNCTION or METHOD-CLOSURE-GENERATOR.
  508.   ;; METHOD-FUNCTION is the documented function of the AMOP.
  509.   ;; METHOD-OPTIMIZED-FUNCTION is the optimized function used by PCL in actual
  510.   ;; method function invocation (METHOD-FUNCTION-FOR-CACHING). Its arguments are
  511.   ;; the actual arguments of method, and it recieves its next-methods by
  512.   ;; looking at the global *NEXT-METHODS*.  Alternatively, if the method's
  513.   ;; body contains slot-value accesses that can be optimized for caching,
  514.   ;; a METHOD-CLOSURE-GENERATOR is stored instead of METHOD-OPTIMIZED-FUNCTION
  515.   ;; to generate an optimized caching function for given parameter types.
  516.   ;;
  517.   (let ((*optimized-method-lambda* NIL))
  518.     (multiple-value-bind (method-lambda initargs)
  519.       (call-make-method-lambda
  520.          generic-function method lambda-expression env)
  521.       (let* ((optimized-method-lambda
  522.                *optimized-method-lambda*)
  523.              (store-method-function-p
  524.                (call-store-method-function-p generic-function method initargs))
  525.              (store-method-optimized-function-p
  526.                (call-store-method-optimized-function-p
  527.                  generic-function method initargs))
  528.              (store-closure-generator-p
  529.                (call-store-closure-generator-p
  530.                  generic-function method initargs))
  531.              (standard-method-lambda-p
  532.                (and (equal (caddr method-lambda)
  533.                            *standard-pcl-make-method-lambda-doc-string*)
  534.                     optimized-method-lambda)))
  535.         (when (and (not standard-method-lambda-p)
  536.                    store-method-optimized-function-p)
  537.           ;;   Somebody modified make-method-lambda, but didn't specify that
  538.           ;; the generic-function doesn't use method-optimized-function.  So,
  539.           ;; to be safe, define the optimized-method-lambda to just call the
  540.           ;; method-lambda code they returned with the default method lambda
  541.           ;; arguments of the generic-function-args and *next-methods*.
  542.           ;;    For efficiency, the user should redefine
  543.           ;; compute-discriminating-function to directly call method-function
  544.           ;; rather than method-function-for-caching, and optionally define
  545.           ;; a generic-function-uses-method-optimized-function-p method on
  546.           ;; the generic-function/method class to return nil so no dummy
  547.           ;; optimized-method-function is created.
  548.           ;;    Alternatively, if the new make-method-lambda returns a lambda
  549.           ;; with the same arguments as a normal method lambda, then the
  550.           ;; make-method-lambda could be designed analogous to the one on
  551.           ;; standard-generic-function/standard-method, and making sure that
  552.           ;; the CADDR of the method-lambda returned equals
  553.           ;; *standard-pcl-make-method-lambda-doc-string* to signify
  554.           ;; that it's safe to use the *optimized-method-lambda* returned.
  555.           (setf optimized-method-lambda
  556.                 `(lambda (&rest generic-function-args)
  557.                    (method-function-funcall (function ,method-lambda)
  558.                                             generic-function-args
  559.                                             (mapcar #'method-function-method
  560.                                                *next-methods*)))))
  561.         (values (when store-method-function-p
  562.                   method-lambda)
  563.                 (when store-method-optimized-function-p
  564.                   optimized-method-lambda)
  565.                 (when store-closure-generator-p
  566.                   (call-make-closure-generator-form generic-function method
  567.                      optimized-method-lambda initargs))
  568.                 initargs)))))
  569.  
  570. (defun make-std-documented-method-function (optimized-function)
  571.   ;; Make a standard documented method-function out of optimized-function.
  572.   #'(lambda (args &rest next-methods)
  573.       (let ((*next-methods*
  574.               (mapcar #'(lambda (method)
  575.                           (or (method-optimized-function method)
  576.                               (method-function-for-caching
  577.                                 method
  578.                                 (mapcar #'pcl::wrapper-of args))))
  579.                       next-methods)))
  580.         (method-function-apply optimized-function args))))
  581.  
  582. (defun early-make-method-lambda (generic-function ; will be nil
  583.                                  method           ; will be nil
  584.                                  lambda-expression
  585.                                  environment)
  586.   (multiple-value-bind (optimized-method-lambda initargs)
  587.       (make-optimized-standard-method-lambda generic-function method
  588.                                              lambda-expression environment)
  589.     (setf *optimized-method-lambda* optimized-method-lambda)
  590.     (values
  591.       (make-documented-standard-method-lambda
  592.          lambda-expression
  593.          environment
  594.          *standard-pcl-make-method-lambda-doc-string*
  595.          (getf initargs :identifier))
  596.       initargs)))
  597.  
  598. (defun make-optimized-standard-method-lambda
  599.        (generic-function method lambda-expression environment)
  600.   ;; Make the standard PCL rev4b optimized method lambda from
  601.   ;; the old expand-method-internal.
  602.   (let* ((method-lambda lambda-expression)
  603.          (lambda-list (cadr lambda-expression))
  604.          (required-parameters
  605.            (let ((collecting NIL))
  606.              (dolist (parameter lambda-list collecting)
  607.                (if (memq parameter lambda-list-keywords)
  608.                    (return collecting)
  609.                  (setf collecting (nconc collecting (list parameter)))))))
  610.  
  611.          (call-next-method-p nil)       ;flag indicating that call-next-method
  612.                                         ;should be in the method definition
  613.          (closurep nil)                 ;flag indicating that #'call-next-method
  614.                                         ;or #'next-method-p was seen in the
  615.                                         ;body of a method
  616.          (next-method-p-p nil)          ;flag indicating that next-method-p
  617.                                         ;should be in the method definition
  618.          (this-method-p nil)            ;flag indicating that this-method
  619.                                         ;should be in the method definition
  620.          (save-original-args nil)       ;flag indicating whether or not the
  621.                                         ;original arguments to the method
  622.                                         ;must be preserved.  This happens
  623.                                         ;for two reasons:
  624.                                         ; - the method takes &mumble args,
  625.                                         ;   so one of the lexical functions
  626.                                         ;   might be used in a default value
  627.                                         ;   form
  628.                                         ; - call-next-method is used without
  629.                                         ;   arguments at least once in the
  630.                                         ;   body of the method
  631.          (original-args ())
  632.          (mumblep nil)                  ;flag indicating whether or not the
  633.                                         ;method takes &mumble arguments
  634.          (applyp nil)                   ;flag indicating whether or not the
  635.                                         ;method takes &mumble arguments --
  636.                                         ;and call-next-method or next-method-p
  637.                                         ;was seen within their defaults
  638.                                         ;somewhere.  If it does, it means
  639.                                         ;call-next-method without arguments
  640.                                         ;must be APPLY'd to original-args.
  641.                                         ;If this gets set true,
  642.                                         ;save-original-args is set so as well
  643.          (aux-bindings ())              ;Suffice to say that &aux is one of
  644.                                         ;damndest things to have put in a
  645.                                         ;language.
  646.          (slots (mapcar #'list required-parameters))
  647.  
  648.          (real-body *expand-defmethod-internal-real-body*)
  649.          (constant-value-p (and real-body
  650.                                 (null (cdr real-body))
  651.                                 (constantp (car real-body))))
  652.          (constant-value (and constant-value-p
  653.                               (eval (car real-body))))
  654.          (plist (if (and constant-value-p
  655.                          (or (typep constant-value '(or number character))
  656.                              (and (symbolp constant-value)
  657.                                   (symbol-package constant-value))))
  658.                     (list :constant-value constant-value)
  659.                     ()))
  660.  
  661.          (walked-lambda nil))
  662.         (labels
  663.              ((walk-function (form context environment)
  664.                  (cond ((not (eq context ':eval)) form)
  665.                        ((not (listp form)) form)
  666.                        ((eq (car form) 'call-next-method)
  667.                         (setq call-next-method-p 't)
  668.                         (unless (cdr form)
  669.                           (setq save-original-args t))
  670.                         form)
  671.                        ((eq (car form) 'next-method-p)
  672.                         (setq next-method-p-p 't)
  673.                         form)
  674.                        ((eq (car form) 'this-method)
  675.                         (setq this-method-p 't)
  676.                         form)
  677.                        ((and (eq (car form) 'function)
  678.                              (cond ((eq (cadr form) 'call-next-method)
  679.                                     (setq call-next-method-p 't)
  680.                                     (setq save-original-args 't)
  681.                                     (setq closurep t)
  682.                                     form)
  683.                                    ((eq (cadr form) 'next-method-p)
  684.                                     (setq next-method-p-p 't)
  685.                                     (setq closurep t)
  686.                                     form)
  687.                                    ((eq (cadr form) 'this-method)
  688.                                     (setq this-method-p 't)
  689.                                     (setq closurep t)
  690.                                     form)
  691.                                    (t nil))))
  692.                        ((and (or (eq (car form) 'slot-value)
  693.                                  (eq (car form) 'set-slot-value)
  694.                                  (eq (car form) 'slot-boundp))
  695.                              (constantp (caddr form)))
  696.                         (let ((parameter
  697.                                (can-optimize-access
  698.                                   form required-parameters environment)))
  699.                           (ecase (car form)
  700.                             (slot-value
  701.                              (optimize-slot-value generic-function method
  702.                                                   slots parameter form))
  703.                             (set-slot-value
  704.                              (optimize-set-slot-value generic-function method
  705.                                                       slots parameter form))
  706.                             (slot-boundp
  707.                              (optimize-slot-boundp generic-function method
  708.                                                    slots parameter form)))))
  709.                        ((and (or (symbolp (car form))
  710.                                  (and (consp (car form))
  711.                                       (eq (caar form) 'setf)))
  712.                              (gboundp (car form))
  713.                              (if (eq *boot-state* 'complete)
  714.                                  (standard-generic-function-p (gdefinition (car form)))
  715.                                  (funcallable-instance-p (gdefinition (car form)))))
  716.                         (optimize-generic-function-call form required-parameters
  717.                            environment))
  718.                        (t form)))
  719.               (need-applyp (form)
  720.                 (if (consp form)
  721.                     (or (need-applyp (car form)) (need-applyp (cdr form)))
  722.                     (memq form '(call-next-method next-method-p this-method)))))
  723.           
  724.           (setq walked-lambda (walk-form method-lambda environment #'walk-function))
  725.  
  726.           ;;
  727.           ;; Add &allow-other-keys to the lambda list as an interim
  728.           ;; way of implementing lambda list congruence rules.
  729.           ;;
  730.           (when (and (memq '&key lambda-list)
  731.                      (not (memq '&allow-other-keys lambda-list)))
  732.             (let* ((rll (reverse lambda-list))
  733.                    (aux (memq '&aux rll)))
  734.               (setq lambda-list
  735.                     (if aux
  736.                         (progn (setf (cdr aux)
  737.                                      (cons '&allow-other-keys (cdr aux)))
  738.                                (nreverse rll))
  739.                         (nconc (nreverse rll) (list '&allow-other-keys))))))
  740.           ;; Scan the lambda list to determine whether this method
  741.           ;; takes &mumble arguments.  If it does, we set save-original-args
  742.           ;; and mumblep true.  We also check to see if a call-next-method or
  743.           ;; next-method-p is somewhere within the argument default value
  744.           ;; forms.  If so, we set applyp to T.
  745.           ;;
  746.           ;; (Note:  This is an optimization of the applyp restriction of
  747.           ;;   March 92 and earlier, which always set it to true if there
  748.           ;;   were any &mumble arguments.  I can't see this causing any
  749.           ;;   problems. -- TL)
  750.           ;; 
  751.           ;; This is also the place where we construct the original
  752.           ;; arguments lambda list if there has to be one.
  753.           (dolist (p lambda-list)
  754.             (if (memq p lambda-list-keywords)
  755.                 (if (eq p '&aux)
  756.                     (progn
  757.                       (setq aux-bindings (cdr (memq '&aux lambda-list)))
  758.                       (return nil))
  759.                     (progn
  760.                       (setq mumblep T
  761.                             applyp (need-applyp lambda-list)
  762.                             save-original-args t)
  763.                       (push '&rest original-args)
  764.                       (push (make-symbol "AMPERSAND-ARGS") original-args)
  765.                       (return nil)))
  766.                 (push (make-symbol (symbol-name p)) original-args)))
  767.           (setq original-args (if save-original-args
  768.                                   (nreverse original-args)
  769.                                   ()))
  770.           
  771.           (multiple-value-bind (ignore walked-declarations walked-lambda-body)
  772.               (extract-declarations (cddr walked-lambda))
  773.             (declare (ignore ignore))
  774.  
  775.             
  776.             (when (some #'cdr slots)
  777.               (setq plist
  778.                     (list* :optimized-slot-indices
  779.                            (mapcan #'(lambda (parameter-entry)
  780.                                        (mapcar #'(lambda (slot-entry)
  781.                                                    (cons (car parameter-entry)
  782.                                                          slot-entry)) 
  783.                                                (cdr parameter-entry)))
  784.                                    slots)
  785.                            plist)))
  786.             (setq plist
  787.                   (list* :needs-next-methods-p
  788.                          (or next-method-p-p call-next-method-p)
  789.                          plist))
  790.  
  791.             ;;; changes are here... (mt)
  792.             (let ((fn-body `(lambda ,lambda-list
  793.                               ,@walked-declarations
  794.                               ,.walked-lambda-body))
  795.                   (method-identifier
  796.                     (when (or this-method-p call-next-method-p)
  797.                       (gentemp
  798.                         (if method
  799.                             (symbol-name (class-name (class-of method)))
  800.                             "STANDARD-METHOD")))))
  801.               (when method-identifier
  802.                 (setf plist (list* :identifier method-identifier plist)))
  803.               (when (or call-next-method-p next-method-p-p this-method-p)
  804.                 (setq fn-body
  805.                      (add-lexical-functions-to-optimized-standard-method-lambda
  806.                                 walked-declarations
  807.                                 walked-lambda-body
  808.                                 fn-body
  809.                                 original-args
  810.                                 lambda-list
  811.                                 save-original-args
  812.                                 mumblep
  813.                                 applyp
  814.                                 aux-bindings
  815.                                 call-next-method-p
  816.                                 next-method-p-p
  817.                                 this-method-p
  818.                                 closurep
  819.                                 method-identifier)))
  820.               (when (call-store-optimized-method-lambda-p
  821.                        generic-function method plist)
  822.                 (setf plist (list* :optimized-method-lambda fn-body plist)))
  823.               (values
  824.                 fn-body
  825.                 plist))))))
  826.  
  827. (defmacro add-lexical-functions-to-optimized-1
  828.     (lambda-list walked-lambda-body call-next-method-p next-method-p-p
  829.      this-method-p identifier)
  830.    ;; OK to use MACROLET, CALL-NEXT-METHOD is always passed some args,
  831.    ;; and all args are mandatory (else APPLYP would be true).
  832.    `(let (,@(when (or next-method-p-p call-next-method-p)
  833.               `((.next-method. (car *next-methods*))))
  834.            ,@(when call-next-method-p
  835.               `((.next-methods. (cdr *next-methods*)))))
  836.        (macrolet (,@(when this-method-p
  837.                      `((this-method ()
  838.                         `(get-method-from-identifier ',',identifier))))
  839.                   ,@(when call-next-method-p
  840.                      `((call-next-method ,lambda-list
  841.                        `(if .next-method.
  842.                             (let ((*next-methods* .next-methods.))
  843.                               (method-function-funcall
  844.                                   .next-method. ,,@lambda-list))
  845.                             (no-next-method-trap
  846.                                ',',identifier ,,@lambda-list)))))
  847.                   ,@(when next-method-p-p
  848.                       `((next-method-p () `(not (null .next-method.))))))
  849.          ,@walked-lambda-body)))
  850.  
  851. (defmacro add-lexical-functions-to-optimized-2
  852.     (lambda-list walked-declarations walked-lambda-body original-args
  853.      aux-bindings call-next-method-p next-method-p-p this-method-p identifier)
  854.    ;; OK to use MACROLET.  CALL-NEXT-METHOD is sometimes called in the
  855.    ;; body with zero args, so we have to save the original args.
  856.    `(let (,@(when (or next-method-p-p call-next-method-p)
  857.               `((.next-method. (car *next-methods*))))
  858.           ,@(when call-next-method-p
  859.               `((.next-methods. (cdr *next-methods*)))))
  860.       (macrolet (,@(when this-method-p
  861.                     `((this-method ()
  862.                        `(get-method-from-identifier ',',identifier))))
  863.                  ,@(when call-next-method-p
  864.                     `((call-next-method (&rest cnm-args)
  865.                         `(if .next-method.
  866.                              (let ((*next-methods* .next-methods.))
  867.                                (method-function-funcall
  868.                                   .next-method.
  869.                                   ,@(if cnm-args cnm-args ',original-args)))
  870.                            (no-next-method-trap ',',identifier ,@cnm-args)))))
  871.                  ,@(when next-method-p-p
  872.                      '((next-method-p ()
  873.                         `(not (null .next-method.))))))
  874.         (let* (,@(mapcar #'list lambda-list original-args)
  875.                ,@aux-bindings)
  876.           ,@walked-declarations
  877.           ,@walked-lambda-body))))
  878.  
  879. (defmacro add-lexical-functions-to-optimized-3
  880.     (walked-lambda original-args call-next-method-p next-method-p-p
  881.      this-method-p identifier)
  882.   ;; OK to use MACROLET.  CALL-NEXT-METHOD is sometimes called in the
  883.   ;; body with zero args, so we have to save the original args.
  884.   `(let (,@(when (or next-method-p-p call-next-method-p)
  885.              `((.next-method. (car *next-methods*))))
  886.          ,@(when call-next-method-p
  887.              `((.next-methods. (cdr *next-methods*)))))
  888.       (macrolet (,@(when this-method-p
  889.                     `((this-method ()
  890.                        `(get-method-from-identifier ',',identifier))))
  891.                  ,@(when call-next-method-p
  892.                     `((call-next-method (&rest cnm-args)
  893.                         `(if .next-method.
  894.                              (let ((*next-methods* .next-methods.))
  895.                                ,(if cnm-args
  896.                                     `(method-function-funcall
  897.                                        .next-method.  ,@cnm-args)
  898.                                   `(method-function-apply
  899.                                      .next-method.
  900.                                      ,@',(remove '&rest original-args))))
  901.                            (no-next-method-trap ',',identifier ,@cnm-args)))))
  902.                  ,@(when next-method-p-p
  903.                      '((next-method-p ()
  904.                         `(not (null .next-method.))))))
  905.         (method-function-apply  (function ,walked-lambda)
  906.                                 ,@(remove '&rest original-args)))))
  907.  
  908. (defmacro add-lexical-functions-to-optimized-4
  909.     (walked-lambda-body call-next-method-p next-method-p-p
  910.      this-method-p identifier)
  911.   ;;
  912.   ;; We don't have to save the original arguments.  In addition,
  913.   ;; this method doesn't take any &mumble arguments that have
  914.   ;; the lexical functions inside their default value forms.
  915.   ;; Closurep is true, however, so the there might be an
  916.   ;; (apply #'call-next-method...), so we can't use MACROLET.
  917.   ;;
  918.   ;; We can expand this into a simple lambda expression with an
  919.   ;; FLET to define the lexical functions.
  920.   ;; 
  921.   `(let (,@(when (or next-method-p-p call-next-method-p)
  922.              `((.next-method. (car *next-methods*))))
  923.          ,@(when call-next-method-p
  924.              `((.next-methods. (cdr *next-methods*)))))
  925.       (flet (,@(and this-method-p
  926.                     `((this-method ()
  927.                         (get-method-from-identifier ',identifier))))
  928.              ,@(and call-next-method-p
  929.                     `((call-next-method (&rest cnm-args)
  930.                         #+Genera
  931.                         (declare (dbg:invisible-frame :clos-internal))
  932.                         (if .next-method.
  933.                             (let ((*next-methods* .next-methods.))
  934.                               (method-function-apply .next-method. cnm-args))
  935.                             (apply #'no-next-method-trap
  936.                                    ',identifier cnm-args)))))
  937.              ,@(and next-method-p-p
  938.                     '((next-method-p ()
  939.                         (not (null .next-method.))))))
  940.         ,@walked-lambda-body)))
  941.  
  942. (defmacro add-lexical-functions-to-optimized-5
  943.     (lambda-list walked-declarations walked-lambda-body original-args
  944.      aux-bindings call-next-method-p next-method-p-p this-method-p identifier)
  945.   ;;
  946.   ;; This method doesn't accept any &mumble arguments that
  947.   ;; might try to call call-next-method or next-method-p.  But we
  948.   ;; do have to save the original arguments (this is because
  949.   ;; call-next-method is being called with no arguments).
  950.   ;; Have to be careful though, there may be multiple calls to
  951.   ;; call-next-method, all we know is that at least one of them
  952.   ;; is with no arguments.
  953.   ;; 
  954.   `(let (,@(when (or next-method-p-p call-next-method-p)
  955.              `((.next-method. (car *next-methods*))))
  956.          ,@(when call-next-method-p
  957.              `((.next-methods. (cdr *next-methods*)))))
  958.       (flet (,@(and this-method-p
  959.                     `((this-method ()
  960.                         (get-method-from-identifier ',identifier))))
  961.              ,@(and call-next-method-p
  962.                     `((call-next-method (&rest cnm-args)
  963.                         (if .next-method.
  964.                             (let ((*next-methods* .next-methods.))
  965.                               (if cnm-args
  966.                                   (method-function-apply .next-method. cnm-args)
  967.                                   (method-function-funcall
  968.                                      .next-method. ,@original-args)))
  969.                             (apply #'no-next-method-trap
  970.                                    ',identifier cnm-args)))))
  971.              ,@(and next-method-p-p
  972.                     '((next-method-p ()
  973.                         (not (null .next-method.))))))
  974.         (let* (,@(mapcar #'list
  975.                          (remtail lambda-list (memq '&aux lambda-list))
  976.                          original-args)
  977.                ,@aux-bindings)
  978.           ,@walked-declarations
  979.           ,@walked-lambda-body))))
  980.  
  981. (defmacro add-lexical-functions-to-optimized-6
  982.     (walked-lambda original-args call-next-method-p next-method-p-p
  983.      this-method-p identifier)
  984.   ;;
  985.   ;; This is the fully general case.
  986.   ;; We must allow for the lexical functions being used inside
  987.   ;; the default value forms of &mumble arguments, and if must
  988.   ;; allow for call-next-method being called with no arguments.
  989.   ;;
  990.   `(let (,@(when (or next-method-p-p call-next-method-p)
  991.              `((.next-method. (car *next-methods*))))
  992.          ,@(when call-next-method-p
  993.              `((.next-methods. (cdr *next-methods*)))))
  994.       (flet (,@(and this-method-p
  995.                     `((this-method ()
  996.                         (get-method-from-identifier ',identifier))))
  997.              ,@(and call-next-method-p
  998.                     `((call-next-method (&rest cnm-args)
  999.                         (if .next-method.
  1000.                             (let ((*next-methods* .next-methods.))
  1001.                               (if cnm-args
  1002.                                   (method-function-apply .next-method. cnm-args)
  1003.                                   (method-function-apply
  1004.                                      .next-method. 
  1005.                                      ,@(remove '&rest original-args))))
  1006.                             (apply #'no-next-method-trap
  1007.                                    ',identifier cnm-args)))))
  1008.              ,@(and next-method-p-p
  1009.                     '((next-method-p ()
  1010.                         (not (null .next-method.))))))
  1011.         (method-function-apply  (function ,walked-lambda)
  1012.                                 ,@(remove '&rest original-args)))))
  1013.  
  1014. (defun add-lexical-functions-to-optimized-standard-method-lambda
  1015.       (walked-declarations
  1016.        walked-lambda-body
  1017.        walked-lambda
  1018.        original-args
  1019.        lambda-list
  1020.        save-original-args
  1021.        mumblep
  1022.        applyp
  1023.        aux-bindings
  1024.        call-next-method-p
  1025.        next-method-p-p
  1026.        this-method-p
  1027.        closurep
  1028.        identifier)
  1029.   (cond ((and (null closurep)
  1030.               (null applyp)
  1031.               (null save-original-args))
  1032.          ;; OK to use MACROLET, CALL-NEXT-METHOD is always passed some args,
  1033.          ;; and all args are mandatory (else APPLYP would be true).
  1034.          `(lambda ,lambda-list
  1035.             ,@walked-declarations
  1036.             (add-lexical-functions-to-optimized-1
  1037.               ,lambda-list ,walked-lambda-body ,call-next-method-p
  1038.               ,next-method-p-p ,this-method-p ,identifier)))
  1039.         ((and (null closurep)
  1040.               (null mumblep)
  1041.               (null applyp)
  1042.               save-original-args)
  1043.          ;; OK to use MACROLET.  CALL-NEXT-METHOD is sometimes called in the
  1044.          ;; body with zero args, so we have to save the original args.
  1045.          `(lambda ,original-args
  1046.             (add-lexical-functions-to-optimized-2
  1047.               ,lambda-list ,walked-declarations ,walked-lambda-body
  1048.               ,original-args ,aux-bindings ,call-next-method-p ,next-method-p-p
  1049.               ,this-method-p ,identifier)))
  1050.         ((and (null closurep)
  1051.               (null applyp)
  1052.               save-original-args)
  1053.          ;; OK to use MACROLET.  CALL-NEXT-METHOD is sometimes called in the
  1054.          ;; body with zero args, so we have to save the original args.
  1055.          `(lambda ,original-args
  1056.             (add-lexical-functions-to-optimized-3
  1057.               ,walked-lambda ,original-args ,call-next-method-p
  1058.               ,next-method-p-p ,this-method-p ,identifier)))
  1059.         ((and (null save-original-args)
  1060.               (null mumblep))
  1061.          ;;
  1062.          ;; We don't have to save the original arguments.  In addition,
  1063.          ;; this method doesn't take any &mumble arguments that have
  1064.          ;; the lexical functions inside their default value forms.
  1065.          ;; Closurep is true, however, so the there might be an
  1066.          ;; (apply #'call-next-method...), so we can't use MACROLET.
  1067.          ;;
  1068.          ;; We can expand this into a simple lambda expression with an
  1069.          ;; FLET to define the lexical functions.
  1070.          ;; 
  1071.          `(lambda ,lambda-list
  1072.             ,@walked-declarations
  1073.             (add-lexical-functions-to-optimized-4
  1074.               ,walked-lambda-body ,call-next-method-p ,next-method-p-p
  1075.               ,this-method-p ,identifier)))
  1076.         ((null mumblep)
  1077.          ;;
  1078.          ;; This method doesn't accept any &mumble arguments that
  1079.          ;; might try to call call-next-method or next-method-p.  But we
  1080.          ;; do have to save the original arguments (this is because
  1081.          ;; call-next-method is being called with no arguments).
  1082.          ;; Have to be careful though, there may be multiple calls to
  1083.          ;; call-next-method, all we know is that at least one of them
  1084.          ;; is with no arguments.
  1085.          ;; 
  1086.          `(lambda ,original-args
  1087.             (add-lexical-functions-to-optimized-5
  1088.               ,lambda-list ,walked-declarations ,walked-lambda-body
  1089.               ,original-args ,aux-bindings ,call-next-method-p ,next-method-p-p
  1090.               ,this-method-p ,identifier)))
  1091.         (t
  1092.          ;;
  1093.          ;; This is the fully general case.
  1094.          ;; We must allow for the lexical functions being used inside
  1095.          ;; the default value forms of &mumble arguments, and if must
  1096.          ;; allow for call-next-method being called with no arguments.
  1097.          ;; 
  1098.          `(lambda ,original-args
  1099.             (add-lexical-functions-to-optimized-6
  1100.               ,walked-lambda ,original-args ,call-next-method-p
  1101.               ,next-method-p-p ,this-method-p ,identifier)))))
  1102.  
  1103.  
  1104. (defun make-documented-standard-method-lambda (lambda-expression
  1105.                                                environment
  1106.                                                &optional
  1107.                                                documentation
  1108.                                                method-identifier)
  1109.   ;;   Make the lambda for the documented AMOP method-function.
  1110.   ;; This is basically the same as make-optimized-standard-method-lambda,
  1111.   ;; except in the form need for the documented method-functions of standard
  1112.   ;; method lambda.  Because the documented standard method functions aren't
  1113.   ;; normally used in PCL's method dispatch, and only exist for correspondence
  1114.   ;; to the AMOP in case somebody needs it, the code produced here is not as
  1115.   ;; optimized as that produced by make-optimized-standard-method-lambda.
  1116.   ;; In particular, it does not perform any of the normal permutation-vector
  1117.   ;; optimizations for slot-value, and doesn't do anything tricky to optimized
  1118.   ;; call-next-methods (add-lexical-functions-to-documented-standard-method-lambda).
  1119.   (let* ((method-lambda lambda-expression)
  1120.          (lambda-list (cadr lambda-expression))
  1121.          (call-next-method-p nil)       ;flag indicating that call-next-method
  1122.                                         ;should be in the method definition
  1123.          (closurep nil)                 ;flag indicating that #'call-next-method
  1124.                                         ;or #'next-method-p was seen in the
  1125.                                         ;body of a method
  1126.          (next-method-p-p nil)          ;flag indicating that next-method-p
  1127.                                         ;should be in the method definition
  1128.          (this-method-p nil)            ;flag indicating that this-method
  1129.                                         ;should be in the method definition
  1130.          (save-original-args nil)       ;flag indicating whether or not the
  1131.                                         ;original arguments to the method
  1132.                                         ;must be preserved.  This happens
  1133.                                         ;for two reasons:
  1134.                                         ; - the method takes &mumble args,
  1135.                                         ;   so one of the lexical functions
  1136.                                         ;   might be used in a default value
  1137.                                         ;   form
  1138.                                         ; - call-next-method is used without
  1139.                                         ;   arguments at least once in the
  1140.                                         ;   body of the method
  1141.          (original-args ())
  1142.          (mumblep nil)                  ;flag indicating whether or not the
  1143.                                         ;method takes &mumble arguments
  1144.          (applyp nil)                   ;flag indicating whether or not the
  1145.                                         ;method takes &mumble arguments --
  1146.                                         ;and call-next-method or next-method-p
  1147.                                         ;was seen within their defaults
  1148.                                         ;somewhere.  If it does, it means
  1149.                                         ;call-next-method without arguments
  1150.                                         ;must be APPLY'd to original-args.
  1151.                                         ;If this gets set true,
  1152.                                         ;save-original-args is set so as well
  1153.          (aux-bindings ())              ;Suffice to say that &aux is one of
  1154.                                         ;damndest things to have put in a
  1155.                                         ;language.
  1156.          (plist ())
  1157.          (walked-lambda nil))
  1158.         (labels
  1159.              ((walk-function (form context environment)
  1160.                  (declare (ignore environment))
  1161.                  (cond ((not (eq context ':eval)) form)
  1162.                        ((not (listp form)) form)
  1163.                        ((eq (car form) 'call-next-method)
  1164.                         (setq call-next-method-p 't)
  1165.                         (unless (cdr form)
  1166.                           (setq save-original-args t))
  1167.                         form)
  1168.                        ((eq (car form) 'next-method-p)
  1169.                         (setq next-method-p-p 't)
  1170.                         form)
  1171.                        ((eq (car form) 'this-method)
  1172.                         (setq this-method-p 't)
  1173.                         form)
  1174.                        ((and (eq (car form) 'function)
  1175.                              (cond ((eq (cadr form) 'call-next-method)
  1176.                                     (setq call-next-method-p 't)
  1177.                                     (setq save-original-args 't)
  1178.                                     (setq closurep t)
  1179.                                     form)
  1180.                                    ((eq (cadr form) 'next-method-p)
  1181.                                     (setq next-method-p-p 't)
  1182.                                     (setq closurep t)
  1183.                                     form)
  1184.                                    ((eq (cadr form) 'this-method)
  1185.                                     (setq this-method-p 't)
  1186.                                     (setq closurep t)
  1187.                                     form)
  1188.                                    (t nil))))
  1189.                        ;; We don't slot values to be optimized for the
  1190.                        ;; documented method lambdas, since they're never
  1191.                        ;; really used anyway.
  1192.                        ((eq (car form) 'slot-value)
  1193.                         `(unoptimized-slot-value ,@(cdr form)))
  1194.                        ((eq (car form) 'set-slot-value)
  1195.                         `(unoptimized-set-slot-value ,@(cdr form)))
  1196.                        (t form)))
  1197.               (need-applyp (form)
  1198.                 (if (consp form)
  1199.                     (or (need-applyp (car form)) (need-applyp (cdr form)))
  1200.                     (memq form '(call-next-method next-method-p this-method)))))
  1201.           
  1202.           (setq walked-lambda (walk-form method-lambda environment #'walk-function))
  1203.  
  1204.           ;;
  1205.           ;; Add &allow-other-keys to the lambda list as an interim
  1206.           ;; way of implementing lambda list congruence rules.
  1207.           ;;
  1208.           (when (and (memq '&key lambda-list)
  1209.                      (not (memq '&allow-other-keys lambda-list)))
  1210.             (let* ((rll (reverse lambda-list))
  1211.                    (aux (memq '&aux rll)))
  1212.               (setq lambda-list
  1213.                     (if aux
  1214.                         (progn (setf (cdr aux)
  1215.                                      (cons '&allow-other-keys (cdr aux)))
  1216.                                (nreverse rll))
  1217.                         (nconc (nreverse rll) (list '&allow-other-keys))))))
  1218.           ;; Scan the lambda list to determine whether this method
  1219.           ;; takes &mumble arguments.  If it does, we set save-original-args
  1220.           ;; and mumblep true.  We also check to see if a call-next-method or
  1221.           ;; next-method-p is somewhere within the argument default value
  1222.           ;; forms.  If so, we set applyp to T.
  1223.           ;;
  1224.           ;; (Note:  This is an optimization of the applyp restriction of
  1225.           ;;   Rev4b and earlier, which always set it to true if there
  1226.           ;;   were any &mumble arguments.  I can't see this causing any
  1227.           ;;   problems. -- TL)
  1228.           ;; 
  1229.           ;; This is also the place where we construct the original
  1230.           ;; arguments lambda list if there has to be one.
  1231.           (dolist (p lambda-list)
  1232.             (if (memq p lambda-list-keywords)
  1233.                 (if (eq p '&aux)
  1234.                     (progn
  1235.                       (setq aux-bindings (cdr (memq '&aux lambda-list)))
  1236.                       (return nil))
  1237.                     (progn
  1238.                       (setq mumblep T
  1239.                             applyp (need-applyp lambda-list)
  1240.                             save-original-args t)
  1241.                       (push '&rest original-args)
  1242.                       (push (make-symbol "AMPERSAND-ARGS") original-args)
  1243.                       (return nil)))
  1244.                 (push (make-symbol (symbol-name p)) original-args)))
  1245.           (setq original-args (if save-original-args
  1246.                                   (nreverse original-args)
  1247.                                   ()))
  1248.           
  1249.           (multiple-value-bind (ignore walked-declarations walked-lambda-body)
  1250.               (extract-declarations (cddr walked-lambda))
  1251.             (declare (ignore ignore))
  1252.  
  1253.             (setq plist
  1254.                   (list* :needs-next-methods-p (or next-method-p-p call-next-method-p)
  1255.                          plist))
  1256.  
  1257.             ;;; changes are here... (mt)
  1258.             (let ((fn-body
  1259.                    `(lambda ,lambda-list
  1260.                        ,@walked-declarations
  1261.                        ,.walked-lambda-body)))
  1262.               (if (or call-next-method-p next-method-p-p this-method-p)
  1263.                   (setf fn-body
  1264.                     (add-lexical-functions-to-documented-standard-method-lambda
  1265.                         walked-declarations
  1266.                         walked-lambda-body
  1267.                         fn-body
  1268.                         original-args
  1269.                         lambda-list
  1270.                         save-original-args
  1271.                         mumblep
  1272.                         applyp
  1273.                         aux-bindings
  1274.                         call-next-method-p
  1275.                         next-method-p-p
  1276.                         this-method-p
  1277.                         closurep
  1278.                         documentation
  1279.                         method-identifier))
  1280.                   (setf fn-body
  1281.                     `(lambda (args &rest next-methods)
  1282.                        ,@(when documentation
  1283.                            (list documentation))
  1284.                        (declare (ignore next-methods))
  1285.                        (apply #',fn-body args))))
  1286.               (values
  1287.                 fn-body
  1288.                 plist))))))
  1289.  
  1290. (defmacro add-lexical-functions-to-documented-general
  1291.     (walked-lambda call-next-method-p next-method-p-p this-method-p identifier)
  1292.   ;;
  1293.   ;; This is the fully general case.
  1294.   ;; We must allow for the lexical functions being used inside
  1295.   ;; the default value forms of &mumble arguments, and if must
  1296.   ;; allow for call-next-method being called with no arguments.
  1297.   ;; 
  1298.   `(let (,@(when (or next-method-p-p call-next-method-p)
  1299.              `((.next-method. (car next-methods))))
  1300.          ,@(when call-next-method-p
  1301.              `((.next-methods. (cdr next-methods)))))
  1302.       (flet (,@(and this-method-p
  1303.                     `((this-method ()
  1304.                         (get-method-from-identifier ',identifier))))
  1305.              ,@(and call-next-method-p
  1306.                     `((call-next-method (&rest cnm-args)
  1307.                         (if .next-method.
  1308.                              (method-function-funcall
  1309.                                 (method-function .next-method.)
  1310.                                 (or cnm-args args)
  1311.                                 .next-methods.)
  1312.                             (no-next-method-trap ',identifier cnm-args)))))
  1313.              ,@(and next-method-p-p
  1314.                     '((next-method-p ()
  1315.                         (not (null .next-method.))))))
  1316.         (method-function-apply (function ,walked-lambda) args))))
  1317.  
  1318. (defun add-lexical-functions-to-documented-standard-method-lambda
  1319.       (walked-declarations
  1320.        walked-lambda-body
  1321.        walked-lambda
  1322.        original-args
  1323.        lambda-list
  1324.        save-original-args
  1325.        mumblep
  1326.        applyp
  1327.        aux-bindings
  1328.        call-next-method-p
  1329.        next-method-p-p
  1330.        this-method-p
  1331.        closurep
  1332.        documentation
  1333.        identifier)
  1334.   (declare (ignore walked-declarations walked-lambda-body original-args
  1335.                    lambda-list save-original-args mumblep applyp aux-bindings
  1336.                    closurep))
  1337.   ;; This could produce more efficient code by using the special case tricks
  1338.   ;; of add-lexical-functions-to-optimized-standard-method-lambda,
  1339.   ;; but documented method lambda's aren't normally used, so it wasn't
  1340.   ;; worth doing here.
  1341.   ;;   NOTE: Contents of documentation must appear in the CADDR of the
  1342.   ;; lambda list returned as shown here to keep tricks of make-method-lambda
  1343.   ;; happy (so it knows that the make-method-lambda used the standard
  1344.   ;; return method.)
  1345.   (cond (t
  1346.          ;;
  1347.          ;; This is the fully general case.
  1348.          ;; We must allow for the lexical functions being used inside
  1349.          ;; the default value forms of &mumble arguments, and if must
  1350.          ;; allow for call-next-method being called with no arguments.
  1351.          ;; 
  1352.          `(lambda (args &rest next-methods)
  1353.             ,@(when documentation
  1354.                 (list documentation))
  1355.             (add-lexical-functions-to-documented-general
  1356.               ,walked-lambda ,call-next-method-p ,next-method-p-p
  1357.               ,this-method-p ,identifier)))))
  1358.  
  1359.  
  1360.  
  1361. (defun no-next-method-trap (method-identifier &rest args)
  1362.   (let ((method (get-method-from-identifier method-identifier)))
  1363.     (if (and method method-identifier)
  1364.         (apply #'no-next-method (method-generic-function method) method args)
  1365.       (error "No next method."))))
  1366.  
  1367. (defun make-parameter-references (specialized-lambda-list
  1368.                                   required-parameters
  1369.                                   declarations
  1370.                                   generic-function-name
  1371.                                   specializers)
  1372.   (flet ((ignoredp (symbol)
  1373.            (dolist (decl (cdar declarations))
  1374.              (when (and (eq (car decl) 'ignore)
  1375.                         (memq symbol (cdr decl)))
  1376.                (return t)))))      
  1377.     (gathering ((references (collecting)))
  1378.       (iterate ((s (list-elements specialized-lambda-list))
  1379.                 (p (list-elements required-parameters)))
  1380.         (progn p)
  1381.         (cond ((not (listp s)))
  1382.               ((ignoredp (car s))
  1383.                (warn "In defmethod ~S ~S, there is a~%~
  1384.                       redundant ignore declaration for the parameter ~S."
  1385.                      generic-function-name
  1386.                      specializers
  1387.                      (car s)))
  1388.               (t
  1389.                (gather (car s) references)))))))
  1390.  
  1391. (defvar *method-identifier-table* (make-hash-table :test #'eq))
  1392.  
  1393. (defun get-method-from-identifier (identifier)
  1394.   (gethash identifier *method-identifier-table*))
  1395.  
  1396. (defun set-get-method-from-identifier (identifier new-method)
  1397.   (setf (gethash identifier *method-identifier-table*) new-method))
  1398.  
  1399. (defsetf get-method-from-identifier set-get-method-from-identifier)
  1400.  
  1401.  
  1402. (defvar *method-function-plist* (make-hash-table :test #'eq))
  1403.  
  1404. (defun method-function-plist (method-function)
  1405.   (gethash method-function *method-function-plist*))
  1406.  
  1407. (defun #-setf SETF\ PCL\ METHOD-FUNCTION-PLIST #+setf (setf method-function-plist)
  1408.        (val method-function)
  1409.   (setf (gethash method-function *method-function-plist*) val))
  1410.  
  1411. (defun method-function-get (method-function key)
  1412.   (getf (method-function-plist method-function) key))
  1413.  
  1414. (defun #-setf SETF\ PCL\ METHOD-FUNCTION-GET #+setf (setf method-function-get)
  1415.        (val method-function key)
  1416.   (setf (getf  (method-function-plist method-function) key) val))
  1417.  
  1418. (defun method-function-method (method-function)
  1419.   (method-function-get method-function 'method))
  1420.  
  1421. (defun set-method-function-method (method-function new-value)
  1422.   (setf (method-function-get method-function 'method) new-value))
  1423.  
  1424. (defsetf method-function-method set-method-function-method)
  1425.  
  1426.  
  1427.  
  1428. (defun load-defmethod
  1429.        (class name quals specls ll doc function optimized-function
  1430.         closure-generator initargs)
  1431.   (when (listp name) (do-standard-defsetf-1 (cadr name)))
  1432.   (let ((method-spec (make-method-spec name quals specls)))
  1433.     (record-definition 'method method-spec)
  1434.     (when function
  1435.       (setq function
  1436.             (set-function-name (method-function-storage-form function)
  1437.                                method-spec)))
  1438.     (when optimized-function
  1439.       (setq optimized-function
  1440.             (set-function-name
  1441.               (method-function-storage-form optimized-function)
  1442.               method-spec)))
  1443.     (when closure-generator
  1444.       (setq closure-generator (method-function-storage-form closure-generator)))
  1445.     (load-defmethod-internal
  1446.       name quals specls ll doc function class
  1447.       optimized-function closure-generator initargs)))
  1448.  
  1449. (defun load-defmethod-internal
  1450.        (gf-spec qualifiers specializers lambda-list doc fn method-class
  1451.         optimized-function closure-generator initargs)
  1452.   (when (listp gf-spec) (do-standard-defsetf-1 (cadr gf-spec)))
  1453.  
  1454.   (let ((method (apply
  1455.                   #'add-named-method
  1456.                   gf-spec method-class
  1457.                   qualifiers specializers lambda-list fn
  1458.                   optimized-function
  1459.                   closure-generator
  1460.                   :documentation doc
  1461.                   :definition-source `((defmethod ,gf-spec
  1462.                                                   ,@qualifiers
  1463.                                                   ,specializers)
  1464.                                        ,(load-truename))
  1465.                   initargs)))
  1466.     (when (and (eq *boot-state* 'complete)
  1467.                (neq (find-class method-class nil)
  1468.                     (generic-function-method-class (gdefinition gf-spec))))
  1469.       (format *error-output*
  1470.               "At the time the method with qualifiers: ~S and~%~
  1471.                specializers: ~S on the generic function ~S~%~
  1472.                was compiled, the method-class for that generic function was~%~
  1473.                ~S.  But, the method class is now ~S, this~%~
  1474.                may mean that this method was compiled improperly."
  1475.               qualifiers specializers gf-spec
  1476.               method-class (class-name (class-of method))))
  1477.     method))
  1478.  
  1479.  
  1480.  
  1481. (defun make-method-spec (gf-spec qualifiers unparsed-specializers)
  1482.   `(method ,gf-spec ,@qualifiers ,unparsed-specializers))
  1483.  
  1484. ;;;; Early generic-function support
  1485. ;;;
  1486. ;;;
  1487. (defvar *early-generic-functions* ())
  1488.  
  1489. (defun ensure-generic-function (function-specifier
  1490.                                 &rest all-keys
  1491.                                 &key environment
  1492.                                 &allow-other-keys)
  1493.   (declare (ignore environment))
  1494.   (let ((existing (and (gboundp function-specifier)                    
  1495.                        (gdefinition function-specifier))))
  1496.     (if (and existing
  1497.              (eq *boot-state* 'complete)
  1498.              (null (generic-function-p existing)))
  1499.         (generic-clobbers-function function-specifier)
  1500.         (apply #'ensure-generic-function-using-class existing function-specifier all-keys))))
  1501.  
  1502. (defun generic-clobbers-function (function-specifier)
  1503.   #+Lispm (zl:signal 'generic-clobbers-function :name function-specifier)
  1504.   #-Lispm (error "~S already names an ordinary function or a macro,~%~
  1505.                   you may want to replace it with a generic function, but doing so~%~
  1506.                   will require that you decide what to do with the existing function~%~
  1507.                   definition.~%~
  1508.                   The PCL-specific function MAKE-SPECIALIZABLE may be useful to you."
  1509.                  function-specifier))
  1510.  
  1511. #+Lispm
  1512. (zl:defflavor generic-clobbers-function (name) (si:error)
  1513.   :initable-instance-variables)
  1514.  
  1515. #+Lispm
  1516. (zl:defmethod #+Genera (dbg:report generic-clobbers-function)
  1517.               #+ti (generic-clobbers-function :report)
  1518.               (stream)
  1519.  (format stream
  1520.          "~S aready names a ~a"
  1521.          name
  1522.          (if (and (symbolp name) (macro-function name)) "macro" "function")))
  1523.  
  1524. #+Genera
  1525. (zl:defmethod (sys:proceed generic-clobbers-function :specialize-it) ()
  1526.   "Make it specializable anyway?"
  1527.   (make-specializable name))
  1528.  
  1529. #+ti
  1530. (zl:defmethod
  1531.      (generic-clobbers-function :case :proceed-asking-user :specialize-it)
  1532.      (continuation ignore)
  1533.   "Make it specializable anyway?"
  1534.   (make-specializable name)
  1535.   (funcall continuation :specialize-it))
  1536.  
  1537. ;;;
  1538. ;;; This is the early definition of ensure-generic-function-using-class.
  1539. ;;; 
  1540. ;;; The static-slots field of the funcallable instances used as early generic
  1541. ;;; functions is used to store the early methods and early discriminator code
  1542. ;;; for the early generic function.  The static slots field of the fins
  1543. ;;; contains a list whose:
  1544. ;;;    CAR    -   a list of the early methods on this early gf
  1545. ;;;    CADR   -   the early discriminator code for this method
  1546. ;;;    
  1547. (defun ensure-generic-function-using-class (existing spec &rest keys
  1548.                                             &key (lambda-list nil lambda-list-p)
  1549.                                             &allow-other-keys)
  1550.   (declare (ignore keys))
  1551.   (if existing
  1552.       existing
  1553.       (unless (assoc spec *generic-function-fixups* :test #'equal)
  1554.         (pushnew spec *early-generic-functions* :test #'equal)
  1555.         (let ((fin (allocate-funcallable-instance-1)))
  1556.           (when (eq spec 'print-object)
  1557.             (set-funcallable-instance-function
  1558.              fin #'(lambda (instance stream)
  1559.                      (printing-random-thing (instance stream)
  1560.                        (format stream "std-instance")))))
  1561.           (setf (gdefinition spec) fin)
  1562.           (when lambda-list-p
  1563.             (proclaim-defgeneric spec lambda-list))
  1564.           (setf (fsc-instance-slots fin) (list nil nil spec))
  1565.           (set-function-name fin spec)
  1566.           fin))))
  1567.  
  1568. (defun early-gf-p (x)
  1569.   (and (fsc-instance-p x)
  1570.        (listp (fsc-instance-slots x))))
  1571.  
  1572. (defmacro early-gf-methods (early-gf)
  1573.   `(let ((fsc-slots (fsc-instance-slots ,early-gf)))
  1574.      (if (listp fsc-slots)
  1575.          (car fsc-slots)
  1576.          ;; This only happens when pcl is loaded on top of itself.
  1577.          (slot-value ,early-gf 'methods))))
  1578.  
  1579. (defmacro set-early-gf-methods (early-gf new-value)
  1580.   `(let ((fsc-slots (fsc-instance-slots ,early-gf)))
  1581.      (if (listp fsc-slots)
  1582.          (setf (car fsc-slots) ,new-value)
  1583.          ;; This only happens when pcl is loaded on top of itself.
  1584.          (setf (slot-value ,early-gf 'methods) ,new-value))))
  1585.  
  1586. (defsetf early-gf-methods set-early-gf-methods)
  1587.  
  1588. (defmacro early-gf-discriminator-code (early-gf);These are macros so that
  1589.   `(cadr (fsc-instance-slots ,early-gf)))       ;they can be setf'd.
  1590.  
  1591. (defun early-gf-name (early-gf)
  1592.   (caddr (fsc-instance-slots early-gf)))
  1593.  
  1594.  
  1595. (defmacro real-ensure-gf-internal (gf-class all-keys env)
  1596.   `(progn
  1597.      (cond ((symbolp ,gf-class)
  1598.             (setq ,gf-class (find-class ,gf-class t ,env)))
  1599.            ((classp ,gf-class))
  1600.            (t
  1601.             (error "The :GENERIC-FUNCTION-CLASS argument (~S) was neither a~%~
  1602.                     class nor a symbol that names a class."
  1603.                    ,gf-class)))
  1604.      (remf ,all-keys :generic-function-class)
  1605.      (remf ,all-keys :environment)
  1606.      (let ((combin (getf ,all-keys :method-combination '.shes-not-there.)))
  1607.        (unless (eq combin '.shes-not-there.)
  1608.          (setf (getf ,all-keys :method-combination)
  1609.                (find-method-combination (class-prototype ,gf-class)
  1610.                                         (car combin)
  1611.                                         (cdr combin)))))
  1612.      ))
  1613.      
  1614. (defun real-ensure-gf-using-class--generic-function
  1615.        (existing
  1616.         function-specifier
  1617.         &rest all-keys
  1618.         &key environment (lambda-list nil lambda-list-p)
  1619.              (generic-function-class 'standard-generic-function gf-class-p)
  1620.         &allow-other-keys)
  1621.   (real-ensure-gf-internal generic-function-class all-keys environment)
  1622.   (unless (or (null gf-class-p)
  1623.               (eq (class-of existing) generic-function-class))
  1624.     (change-class existing generic-function-class))
  1625.   (prog1
  1626.       (apply #'reinitialize-instance existing all-keys)
  1627.     (when lambda-list-p
  1628.       (proclaim-defgeneric function-specifier lambda-list))))
  1629.  
  1630. (defun real-ensure-gf-using-class--null
  1631.        (existing
  1632.         function-specifier
  1633.         &rest all-keys
  1634.         &key environment (lambda-list nil lambda-list-p)
  1635.              (generic-function-class 'standard-generic-function)
  1636.         &allow-other-keys)
  1637.   (declare (ignore existing))
  1638.   (real-ensure-gf-internal generic-function-class all-keys environment)
  1639.   (prog1
  1640.       (setf (gdefinition function-specifier)
  1641.             (apply #'make-instance generic-function-class 
  1642.                    :name function-specifier all-keys))
  1643.     (when lambda-list-p
  1644.       (proclaim-defgeneric function-specifier lambda-list))))
  1645.  
  1646.  
  1647.  
  1648.  
  1649. (defun early-make-a-method
  1650.    (class qualifiers arglist specializers function optimized-function
  1651.     closure-generator doc &optional slot-name other-initargs)
  1652.   (let ((parsed ())
  1653.         (unparsed ()))
  1654.     ;; Figure out whether we got class objects or class names as the
  1655.     ;; specializers and set parsed and unparsed appropriately.  If we
  1656.     ;; got class objects, then we can compute unparsed, but if we got
  1657.     ;; class names we don't try to compute parsed.
  1658.     ;; 
  1659.     ;; Note that the use of not symbolp in this call to every should be
  1660.     ;; read as 'classp' we can't use classp itself because it doesn't
  1661.     ;; exist yet.
  1662.     (setf function           (method-function-storage-form function))
  1663.     (setf optimized-function (method-function-storage-form optimized-function))
  1664.     (setf closure-generator  (method-function-storage-form closure-generator))
  1665.     (if (every #'(lambda (s) (not (symbolp s))) specializers)
  1666.         (setq parsed specializers
  1667.               unparsed (mapcar #'(lambda (s)
  1668.                                    (if (eq s 't) 't (class-name s)))
  1669.                                specializers))
  1670.         (setq unparsed specializers
  1671.               parsed ()))
  1672.     (list :early-method           ;This is an early method dammit!
  1673.           
  1674.           (or optimized-function
  1675.               (make-not-for-caching-method-function closure-generator))
  1676.                                   ;Function is here for the benefit
  1677.                                   ;of early-lookup-method.
  1678.           
  1679.           parsed                  ;The parsed specializers.  This is used
  1680.                                   ;by early-method-specializers to cache
  1681.                                   ;the parse.  Note that this only comes
  1682.                                   ;into play when there is more than one
  1683.                                   ;early method on an early gf.
  1684.           
  1685.           (list class             ;A list to which real-make-a-method
  1686.                 qualifiers        ;can be applied to make a real method
  1687.                 arglist           ;corresponding to this early one.
  1688.                 unparsed
  1689.                 function
  1690.                 optimized-function
  1691.                 closure-generator
  1692.                 doc
  1693.                 slot-name
  1694.                 other-initargs)
  1695.           )))
  1696.  
  1697. (defun real-make-a-method
  1698.   (class qualifiers lambda-list specializers function optimized-function
  1699.    closure-generator doc &optional slot-name other-initargs)
  1700.   (setq specializers (parse-specializers specializers))
  1701.   (apply #'make-instance
  1702.          class
  1703.          :qualifiers qualifiers
  1704.          :lambda-list lambda-list
  1705.          :specializers specializers
  1706.          :function           (method-function-storage-form function)
  1707.          :optimized-function (method-function-storage-form optimized-function)
  1708.          :closure-generator  (method-function-storage-form closure-generator)
  1709.          :documentation doc
  1710.          :slot-name slot-name
  1711.          :allow-other-keys t
  1712.          other-initargs))
  1713.  
  1714. (defun early-method-function (early-method)
  1715.   (cadr early-method))
  1716.  
  1717. (defun early-method-standard-accessor-p (early-method)
  1718.   (let ((class (car (cadddr early-method))))
  1719.     (or (eq class 'standard-reader-method)
  1720.         (eq class 'standard-writer-method)
  1721.         (eq class 'standard-boundp-method))))
  1722.  
  1723. ;;;
  1724. ;;; Fetch the specializers of an early method.  This is basically just a
  1725. ;;; simple accessor except that when the second argument is t, this converts
  1726. ;;; the specializers from symbols into class objects.  The class objects
  1727. ;;; are cached in the early method, this makes bootstrapping faster because
  1728. ;;; the class objects only have to be computed once.
  1729. ;;; NOTE:
  1730. ;;;  the second argument should only be passed as T by early-lookup-method.
  1731. ;;;  this is to implement the rule that only when there is more than one
  1732. ;;;  early method on a generic function is the conversion from class names
  1733. ;;;  to class objects done.
  1734. ;;;  the corresponds to the fact that we are only allowed to have one method
  1735. ;;;  on any generic function up until the time classes exist.
  1736. ;;;  
  1737. (defun early-method-specializers (early-method &optional objectsp)
  1738.   (if (and (listp early-method)
  1739.            (eq (car early-method) :early-method))
  1740.       (cond ((eq objectsp 't)
  1741.              (or (caddr early-method)
  1742.                  (setf (caddr early-method)
  1743.                        (mapcar #'find-class (cadddr (cadddr early-method))))))
  1744.             (t
  1745.              (cadddr (cadddr early-method))))
  1746.       (error "~S is not an early-method." early-method)))
  1747.  
  1748. (defun early-method-qualifiers (early-method)
  1749.   (cadr (cadddr early-method)))
  1750.  
  1751. (defun early-add-named-method (generic-function-name
  1752.                                method-class
  1753.                                qualifiers
  1754.                                specializers
  1755.                                arglist
  1756.                                function
  1757.                                optimized-function
  1758.                                closure-generator
  1759.                                &rest other-initargs)
  1760.   (let* ((gf (ensure-generic-function generic-function-name))
  1761.          (existing
  1762.            (dolist (m (early-gf-methods gf))
  1763.              (when (and (equal (early-method-specializers m) specializers)
  1764.                         (equal (early-method-qualifiers m) qualifiers))
  1765.                (return m))))
  1766.          (new (make-a-method method-class
  1767.                              qualifiers
  1768.                              arglist
  1769.                              specializers
  1770.                              function
  1771.                              optimized-function
  1772.                              closure-generator
  1773.                              ()
  1774.                              ()
  1775.                              other-initargs)))
  1776.     (when existing (remove-method gf existing))
  1777.     (add-method gf new)))
  1778.  
  1779. ;;;
  1780. ;;; This is the early version of add-method.  Later this will become a
  1781. ;;; generic function.  See fix-early-generic-functions which has special
  1782. ;;; knowledge about add-method.
  1783. ;;;
  1784. (defun add-method (generic-function method)
  1785.   (when (not (fsc-instance-p generic-function))
  1786.     (error "Early add-method didn't get a funcallable instance."))
  1787.   (when (not (and (listp method) (eq (car method) :early-method)))
  1788.     (error "Early add-method didn't get an early method."))
  1789.   (push method (early-gf-methods generic-function))
  1790.   (early-update-discriminator-code generic-function))
  1791.  
  1792. ;;;
  1793. ;;; This is the early version of remove method.
  1794. ;;;
  1795. (defun remove-method (generic-function method)
  1796.   (when (not (fsc-instance-p generic-function))
  1797.     (error "Early remove-method didn't get a funcallable instance."))
  1798.   (when (not (and (listp method) (eq (car method) :early-method)))
  1799.     (error "Early remove-method didn't get an early method."))
  1800.   (setf (early-gf-methods generic-function)
  1801.         (remove method (early-gf-methods generic-function)))
  1802.   (early-update-discriminator-code generic-function))
  1803.  
  1804. ;;;
  1805. ;;; And the early version of get-method.
  1806. ;;;
  1807. (defun get-method (generic-function qualifiers specializers
  1808.                                     &optional (errorp t))
  1809.   (if (early-gf-p generic-function)
  1810.       (or (dolist (m (early-gf-methods generic-function))
  1811.             (when (and (or (equal (early-method-specializers m nil)
  1812.                                   specializers)
  1813.                            (equal (early-method-specializers m 't)
  1814.                                   specializers))
  1815.                        (equal (early-method-qualifiers m) qualifiers))
  1816.               (return m)))
  1817.           (if errorp
  1818.               (error "Can't get early method.")
  1819.               nil))
  1820.       (real-get-method generic-function qualifiers specializers errorp)))
  1821.  
  1822. (defun early-update-discriminator-code (generic-function)
  1823.   (let* ((methods (early-gf-methods generic-function))
  1824.          (early-dfun
  1825.            (cond ((null methods)
  1826.                   #'(lambda (&rest ignore)
  1827.                       (declare (ignore ignore))
  1828.                       (error "Called an early generic-function that ~
  1829.                               has no methods?")))
  1830.                  ((null (cdr methods))
  1831.                   ;; If there is only one method, just use that method's
  1832.                   ;; function.  This corresponds to the important fact
  1833.                   ;; that early generic-functions with only one method
  1834.                   ;; always call that method when they are called.  If
  1835.                   ;; there is more than one method, we have to install
  1836.                   ;; a simple little discriminator-code for this generic
  1837.                   ;; function.
  1838.                   (cadr (car methods)))
  1839.                  (t
  1840.                   (set-function-name 
  1841.                    #'(lambda (&rest args) (early-dfun methods args))
  1842.                    (early-gf-name generic-function))))))
  1843.     (set-funcallable-instance-function generic-function early-dfun)
  1844.     (setf (early-gf-discriminator-code generic-function) early-dfun)))
  1845.  
  1846. (defun early-get-cpl (object)
  1847.   (bootstrap-get-slot 'std-class
  1848.                       (class-of object)
  1849.                       'class-precedence-list))
  1850.  
  1851. (defun early-sort-methods (list args)
  1852.   (if (null (cdr list))
  1853.       list
  1854.       (sort list
  1855.             #'(lambda (specls-1 specls-2)
  1856.                 (iterate ((s1 (list-elements specls-1))
  1857.                           (s2 (list-elements specls-2))
  1858.                           (a (list-elements args)))
  1859.                   (cond ((eq s1 s2))
  1860.                         ((eq s2 *the-class-t*) (return t))
  1861.                         ((eq s1 *the-class-t*) (return nil))
  1862.                         (t (return (memq s2 (memq s1 (early-get-cpl a))))))))
  1863.             :key #'(lambda (em) (early-method-specializers em t)))))
  1864.  
  1865. (defun early-dfun (methods args)
  1866.   (let ((primary ())
  1867.         (before ())
  1868.         (after ())
  1869.         (around ()))
  1870.     (dolist (method methods)
  1871.       (let* ((specializers (early-method-specializers method t))
  1872.              (qualifiers (early-method-qualifiers method))
  1873.              (args args)
  1874.              (specs specializers))
  1875.         (when (loop
  1876.                 (when (or (null args)
  1877.                           (null specs))
  1878.                   ;; If we are out of specs, then we must be in the optional,
  1879.                   ;; rest or keywords arguments.  This method is applicable
  1880.                   ;; to these arguments.  Return T.
  1881.                   (return t))
  1882.                 (let ((arg (pop args))
  1883.                       (spec (pop specs)))
  1884.                   (unless (or (eq spec *the-class-t*)
  1885.                               (memq spec (early-get-cpl arg)))
  1886.                     (return nil))))
  1887.           (cond ((null qualifiers) (push method primary))
  1888.                 ((equal qualifiers '(:before)) (push method before))
  1889.                 ((equal qualifiers '(:after))  (push method after))
  1890.                 ((equal qualifiers '(:around)) (push method around))
  1891.                 (t
  1892.                  (error "Unrecognized qualifier in early method."))))))
  1893.     (setq primary (early-sort-methods primary args)
  1894.           before  (early-sort-methods before  args)
  1895.           after   (early-sort-methods after   args)
  1896.           around  (early-sort-methods around  args))
  1897.     (flet ((do-main-combined-method (&rest arguments)
  1898.              (dolist (m before) (apply (cadr m) arguments))
  1899.              (multiple-value-prog1
  1900.                (let ((*next-methods* (mapcar #'car (cdr primary))))
  1901.                  (apply (cadar primary) arguments))
  1902.                (dolist (m after) (apply (cadr m) arguments)))))
  1903.       (if (null around)
  1904.           (apply #'do-main-combined-method args)
  1905.           (let ((*next-methods*
  1906.                   (append (mapcar #'cadr (cdr around))
  1907.                           (list #'do-main-combined-method))))
  1908.             (apply (cadar around) args))))))
  1909.  
  1910. (defvar *fegf-debug-p* nil)
  1911.  
  1912. (defun fix-early-generic-functions (&optional (noisyp *fegf-debug-p*))
  1913.   (allocate-instance (find-class 'standard-generic-function)) ;Be sure this
  1914.                                                               ;class has an
  1915.                                                               ;instance.
  1916.   (let* ((class (find-class 'standard-generic-function))
  1917.          (wrapper (class-wrapper class))
  1918.          (statics-slots-copy
  1919.            (wrapper-allocate-static-slot-storage-copy wrapper))
  1920.          (default-initargs
  1921.            (default-initargs class () (class-default-initargs class)))
  1922.          #+Lucid
  1923.          (lucid::*redefinition-action* nil))
  1924.     (flet ((fix-structure (gf)
  1925.              (let ((static-slots
  1926.                     (%allocate-static-slot-storage--class statics-slots-copy)))
  1927.                (setf (fsc-instance-wrapper gf) wrapper
  1928.                      (fsc-instance-slots gf) static-slots))))
  1929.       (let ((accessors nil))
  1930.         (dolist (early-gf-spec *early-generic-functions*)
  1931.           (when (every #'early-method-standard-accessor-p
  1932.                        (early-gf-methods (gdefinition early-gf-spec)))
  1933.             (push early-gf-spec accessors)))
  1934.         (dolist (spec (nconc accessors
  1935.                              '(slot-boundp-using-class
  1936.                                (setf slot-value-using-class)
  1937.                                slot-value-using-class)))
  1938.           (setq *early-generic-functions* 
  1939.                 (cons spec (delete spec *early-generic-functions*
  1940.                                    :test #'equal)))))
  1941.       (dolist (early-gf-spec *early-generic-functions*)
  1942.         (when noisyp (format t "~&~S..." early-gf-spec))
  1943.         (let* ((early-gf (gdefinition early-gf-spec))
  1944.                (early-static-slots
  1945.                 (fsc-instance-slots early-gf))
  1946.                (early-discriminator-code nil)
  1947.                (early-methods nil)
  1948.                (aborted t))
  1949.           (flet ((trampoline (&rest args)
  1950.                    (apply early-discriminator-code args)))
  1951.             (if (not (listp early-static-slots))
  1952.                 (when noisyp (format t "already fixed?"))
  1953.                 (unwind-protect
  1954.                      (progn
  1955.                        (setq early-discriminator-code
  1956.                              (early-gf-discriminator-code early-gf))
  1957.                        (setq early-methods
  1958.                              (early-gf-methods early-gf))
  1959.                        (setf (gdefinition early-gf-spec) #'trampoline)
  1960.                        (when noisyp (format t "trampoline..."))
  1961.                        (fix-structure early-gf)
  1962.                        (when noisyp (format t "fixed..."))
  1963.                        (apply #'initialize-instance early-gf
  1964.                               :name early-gf-spec default-initargs)
  1965.                        (loop
  1966.                         (when (null early-methods) (return nil))
  1967.                         (let ((early-method (pop early-methods)))
  1968.                           (destructuring-bind
  1969.                              (class quals lambda-list specs fn
  1970.                               optimized-function closure-generator doc
  1971.                               slot-name other-initargs)
  1972.                               (cadddr early-method)
  1973.                             (setq specs
  1974.                                   (early-method-specializers early-method t))
  1975.                             (let ((method (real-make-a-method
  1976.                                               class
  1977.                                               quals
  1978.                                               lambda-list
  1979.                                               specs
  1980.                                               fn
  1981.                                               optimized-function
  1982.                                               closure-generator
  1983.                                               doc
  1984.                                               slot-name
  1985.                                               other-initargs)))
  1986.                               (real-add-method early-gf method)
  1987.                               (when noisyp (format t "m"))))))
  1988.                        (setf (generic-function-name early-gf) early-gf-spec)
  1989.                        (setq aborted nil))
  1990.                   (setf (gdefinition early-gf-spec) early-gf)
  1991.                   (when noisyp (format t "."))
  1992.                   (when aborted
  1993.                     (setf (fsc-instance-slots early-gf)
  1994.                           early-static-slots))))))))
  1995.           
  1996.     (dolist (fns *early-functions*)
  1997.       (setf (symbol-function (car fns)) (symbol-function (caddr fns))))
  1998.       
  1999.     (dolist (fixup *generic-function-fixups*)
  2000.       (let ((fspec (car fixup))
  2001.             (methods (cdr fixup))
  2002.             (gf (make-instance 'standard-generic-function)))
  2003.         (set-function-name gf fspec)
  2004.         (setf (generic-function-name gf) fspec)
  2005.         (loop 
  2006.          (when (null methods) (return nil))
  2007.          (let ((method (pop methods)))
  2008.            (destructuring-bind (lambda-list specializers method-fn-name)
  2009.                method
  2010.               (let*
  2011.                 ((optimized-function
  2012.                    (if method-fn-name
  2013.                        (symbol-function method-fn-name)
  2014.                        (symbol-function fspec)))
  2015.                  (function
  2016.                    (when (call-store-method-function-p
  2017.                            gf
  2018.                            (class-prototype *the-class-standard-method*)
  2019.                            nil)
  2020.                       (make-std-documented-method-function
  2021.                         optimized-function)))
  2022.                  (method (make-a-method 'standard-method
  2023.                                         ()
  2024.                                         lambda-list
  2025.                                         specializers
  2026.                                         function
  2027.                                         optimized-function
  2028.                                         nil
  2029.                                         nil)))
  2030.                (real-add-method gf method)))))
  2031.         (setf (gdefinition fspec) gf)))))
  2032.  
  2033.  
  2034. ;;;
  2035. ;;; parse-defmethod is used by defmethod to parse the &rest argument into
  2036. ;;; the 'real' arguments.  This is where the syntax of defmethod is really
  2037. ;;; implemented.
  2038. ;;; 
  2039. (defun parse-defmethod (cdr-of-form)
  2040.   (declare (values name qualifiers specialized-lambda-list body))
  2041.   (let ((name (pop cdr-of-form))
  2042.         (qualifiers ())
  2043.         (spec-ll ()))
  2044.     (loop (if (and (car cdr-of-form) (atom (car cdr-of-form)))
  2045.               (push (pop cdr-of-form) qualifiers)
  2046.               (return (setq qualifiers (nreverse qualifiers)))))
  2047.     (setq spec-ll (pop cdr-of-form))
  2048.     (values name qualifiers spec-ll cdr-of-form)))
  2049.  
  2050. (defun parse-specializers (specializers)
  2051.   (flet ((parse (spec)
  2052.            (let ((result (specializer-from-type spec)))
  2053.              (if (specializerp result)
  2054.                  result
  2055.                  (if (symbolp spec)
  2056.                      (error "~S used as a specializer,~%~
  2057.                              but is not the name of a class."
  2058.                             spec)
  2059.                      (error "~S is not a legal specializer." spec))))))
  2060.     (mapcar #'parse specializers)))
  2061.  
  2062. (defun unparse-specializers (specializers-or-method)
  2063.   (if (listp specializers-or-method)
  2064.       (flet ((unparse (spec)
  2065.                (if (specializerp spec)
  2066.                    (let ((type (specializer-type spec)))
  2067.                      (if (and (consp type)
  2068.                               (eq (car type) 'class))
  2069.                          (let* ((class (cadr type))
  2070.                                 (class-name (class-name class)))
  2071.                            (if (eq class (find-class class-name nil))
  2072.                                class-name
  2073.                                type))
  2074.                          type))
  2075.                    (error "~S is not a legal specializer." spec))))
  2076.         (mapcar #'unparse specializers-or-method))
  2077.       (unparse-specializers (method-specializers specializers-or-method))))
  2078.  
  2079.  
  2080.  
  2081. (defun extract-parameters (specialized-lambda-list)
  2082.   (multiple-value-bind (parameters ignore1 ignore2)
  2083.       (parse-specialized-lambda-list specialized-lambda-list)
  2084.     (declare (ignore ignore1 ignore2))
  2085.     parameters))
  2086.  
  2087. (defun extract-lambda-list (specialized-lambda-list)
  2088.   (multiple-value-bind (ignore1 lambda-list ignore2)
  2089.       (parse-specialized-lambda-list specialized-lambda-list)
  2090.     (declare (ignore ignore1 ignore2))
  2091.     lambda-list))
  2092.  
  2093. (defun extract-specializer-names (specialized-lambda-list)
  2094.   (multiple-value-bind (ignore1 ignore2 specializers)
  2095.       (parse-specialized-lambda-list specialized-lambda-list)
  2096.     (declare (ignore ignore1 ignore2))
  2097.     specializers))
  2098.  
  2099. (defun extract-required-parameters (specialized-lambda-list)
  2100.   (multiple-value-bind (ignore1 ignore2 ignore3 required-parameters)
  2101.       (parse-specialized-lambda-list specialized-lambda-list)
  2102.     (declare (ignore ignore1 ignore2 ignore3))
  2103.     required-parameters))
  2104.  
  2105. (defun parse-specialized-lambda-list (arglist &optional post-keyword)
  2106.   (declare (values parameters lambda-list specializers required-parameters))
  2107.   (let ((arg (car arglist)))
  2108.     (cond ((null arglist) (values nil nil nil nil))
  2109.           ((eq arg '&aux)
  2110.            (values nil arglist nil nil))
  2111.           ((memq arg lambda-list-keywords)
  2112.            (unless (memq arg '(&optional &rest &key &allow-other-keys &aux))
  2113.              ;; Warn about non-standard lambda-list-keywords, but then
  2114.              ;; go on to treat them like a standard lambda-list-keyword
  2115.              ;; what with the warning its probably ok.
  2116.              (warn "Unrecognized lambda-list keyword ~S in arglist.~%~
  2117.                     Assuming that the symbols following it are parameters,~%~
  2118.                     and not allowing any parameter specializers to follow~%~
  2119.                     to follow it."
  2120.                    arg))
  2121.            ;; When we are at a lambda-list-keyword, the parameters don't
  2122.            ;; include the lambda-list-keyword; the lambda-list does include
  2123.            ;; the lambda-list-keyword; and no specializers are allowed to
  2124.            ;; follow the lambda-list-keywords (at least for now).
  2125.            (multiple-value-bind (parameters lambda-list)
  2126.                (parse-specialized-lambda-list (cdr arglist) t)
  2127.              (declare (type list parameters lambda-list))
  2128.              (values parameters
  2129.                      (cons arg lambda-list)
  2130.                      ()
  2131.                      ())))
  2132.           (post-keyword
  2133.            ;; After a lambda-list-keyword there can be no specializers.
  2134.            (multiple-value-bind (parameters lambda-list)
  2135.                (parse-specialized-lambda-list (cdr arglist) t)         
  2136.              (values (cons (if (listp arg) (car arg) arg) parameters)
  2137.                      (cons arg lambda-list)
  2138.                      ()
  2139.                      ())))
  2140.           (t
  2141.            (multiple-value-bind (parameters lambda-list specializers required)
  2142.                (parse-specialized-lambda-list (cdr arglist))
  2143.              (values (cons (if (listp arg) (car arg) arg) parameters)
  2144.                      (cons (if (listp arg) (car arg) arg) lambda-list)
  2145.                      (cons (if (listp arg) (cadr arg) 't) specializers)
  2146.                      (cons (if (listp arg) (car arg) arg) required)))))))
  2147.  
  2148.  
  2149. (eval-when (load eval)
  2150.   (setq *boot-state* 'early))
  2151.  
  2152.  
  2153. #-cmu
  2154. (defmacro symbol-macrolet (bindings &body body &environment env)
  2155.   (let ((specs (mapcar #'(lambda (binding)
  2156.                            (list (car binding)
  2157.                                  (variable-lexical-p (car binding) env)
  2158.                                  (cadr binding)))
  2159.                        bindings)))
  2160.     (walk-form `(progn ,@body)
  2161.                env
  2162.                #'(lambda (f c e)
  2163.                    (expand-symbol-macrolet-internal specs f c e)))))
  2164.  
  2165. #-cmu
  2166. (defun expand-symbol-macrolet-internal (specs form context env)
  2167.   (let ((entry nil))
  2168.     (cond ((not (eq context :eval)) form)
  2169.           ((symbolp form)
  2170.            (if (and (setq entry (assoc form specs))
  2171.                     (eq (cadr entry) (variable-lexical-p form env)))
  2172.                (caddr entry)
  2173.                form))
  2174.           ((not (listp form)) form)
  2175.           ((member (car form) '(setq setf))
  2176.            ;; Have to be careful.  We must only convert the form to a SETF
  2177.            ;; form when we convert one of the 'logical' variables to a form
  2178.            ;; Otherwise we will get looping in implementations where setf
  2179.            ;; is a macro which expands into setq.
  2180.            (let ((kind (car form)))
  2181.              (labels ((scan-setf (tail)
  2182.                         (if (null tail)
  2183.                             nil
  2184.                             (walker::relist*
  2185.                               tail
  2186.                               (if (and (setq entry (assoc (car tail) specs))
  2187.                                        (eq (cadr entry)
  2188.                                            (variable-lexical-p (car tail)
  2189.                                                                env)))
  2190.                                   (progn (setq kind 'setf)
  2191.                                          (caddr entry))
  2192.                                   (car tail))
  2193.                               (cadr tail)
  2194.                               (scan-setf (cddr tail))))))
  2195.                (let (new-tail)
  2196.                  (setq new-tail (scan-setf (cdr form)))
  2197.                  (walker::recons form kind new-tail)))))
  2198.           ((eq (car form) 'multiple-value-setq)
  2199.            (let* ((vars (cadr form))
  2200.                   (gensyms (mapcar #'(lambda (i) (declare (ignore i)) (gensym))
  2201.                                    vars)))
  2202.              `(multiple-value-bind ,gensyms 
  2203.                   ,(caddr form)
  2204.                 .,(reverse (mapcar #'(lambda (v g) `(setf ,v ,g))
  2205.                                    vars
  2206.                                    gensyms)))))
  2207.           (t form))))
  2208.  
  2209. (defmacro with-slots (slots instance &body body)
  2210.   (let ((in (gensym)))
  2211.     `(let ((,in ,instance))
  2212.        #+cmu (declare (ext::ignorable ,in))
  2213.        ,@(let ((instance (un-the instance)))
  2214.            (and (symbolp instance)
  2215.                 `((declare (variable-rebinding ,in ,instance)))))
  2216.        ,in
  2217.        (symbol-macrolet ,(mapcar #'(lambda (slot-entry)
  2218.                                      (let ((variable-name 
  2219.                                             (if (symbolp slot-entry)
  2220.                                                 slot-entry
  2221.                                                 (car slot-entry)))
  2222.                                            (slot-name
  2223.                                             (if (symbolp slot-entry)
  2224.                                                 slot-entry
  2225.                                                 (cadr slot-entry))))
  2226.                                        `(,variable-name
  2227.                                           (slot-value ,in ',slot-name))))
  2228.                                  slots)
  2229.                         ,@body))))
  2230.  
  2231. (defmacro with-accessors (slots instance &body body)
  2232.   (let ((in (gensym)))
  2233.     `(let ((,in ,instance))
  2234.        #+cmu (declare (ext::ignorable ,in))
  2235.        ,@(let ((instance (un-the instance)))
  2236.            (and (symbolp instance)
  2237.                 `((declare (variable-rebinding ,in ,instance)))))
  2238.        ,in
  2239.        (symbol-macrolet ,(mapcar #'(lambda (slot-entry)
  2240.                                    (let ((variable-name (car slot-entry))
  2241.                                          (accessor-name (cadr slot-entry)))
  2242.                                      `(,variable-name
  2243.                                         (,accessor-name ,in))))
  2244.                                slots)
  2245.           ,@body))))
  2246.  
  2247.  
  2248.